#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "Tree.h"

typedef struct nodeT{
	char * key;
	int u_key;
	int sons_qty;
	struct nodeT ** sons;
}nodeT;

int unique = 0;

/* Funcion que crea un nuevo nodo.
 * Recibe un puntero a un string
 * Devuelve el puntero al nodo creado
 */

struct nodeT *
creaNodo(char * str)
{
	nodeT * node;

	node = malloc(sizeof(struct nodeT));
	if ( node == NULL ){
		return NULL;
	}
	/* Pudimos alocar, ahora alocamos para la key e inicializamos */
	node->key = calloc(strlen(str) + 1, 1);
	if(node->key == NULL){
		free(node);
		return NULL;
	}
	strcpy(node->key, str);
	node->u_key = unique;
	unique++;
	node->sons_qty = 0;
	node->sons = NULL;

	return node;
}

struct nodeT *
llenaHijos(nodeT * padre, int qty, ...)
{
	int i;
	va_list ap;
	nodeT * son;
	/* Alocamos memoria para los hijos */

	va_start(ap, qty);

	if ( padre->sons == NULL){
		padre->sons = calloc(qty, sizeof(struct nodeT *));
		if( padre->sons == NULL){
			free(padre);
			return NULL;
		}
	}else{
		padre->sons = realloc(padre->sons, sizeof(struct nodeT *)*(padre->sons_qty + qty));
		if ( padre->sons == NULL){
			free(padre);
			return NULL;
		}
	}

	for(i= padre->sons_qty; i<padre->sons_qty+qty; i++){
		son = va_arg(ap, struct nodeT *);
		padre->sons[i] = son;
	}
	padre->sons_qty += qty;
	va_end(ap);

	return padre;
}

struct nodeT *
llenaHijosIzq(struct nodeT * padre, int qty, ...)
{
	int i, j;
	va_list ap;
	nodeT * son;
	/* Alocamos memoria para los hijos */

	va_start(ap, qty);

	if ( padre->sons == NULL){
		padre->sons = calloc(qty, sizeof(struct nodeT *));
		if( padre->sons == NULL){
			free(padre);
			return NULL;
		}
	}else{
		padre->sons = realloc(padre->sons, sizeof(struct nodeT *)*(padre->sons_qty + qty));
		if ( padre->sons == NULL){
			free(padre);
			return NULL;
		}
	}

	for (j = padre->sons_qty; j >= 0; j--)
	{
		padre->sons[j] = padre->sons[j-1];
	}

	for(i= padre->sons_qty; i<padre->sons_qty+qty; i++){
			son = va_arg(ap, struct nodeT *);
	}

	padre->sons[0] = son;


	padre->sons_qty += qty;
	va_end(ap);

	return padre;
}

void
PrintTree(struct nodeT * root, int level)
{
	int i;
	if (root == NULL)
		return;
	for(i=0; i < level; i++)
		fprintf(stdout, "\t");
	fprintf(stdout, "%s->%d\n", root->key, root->u_key);
	for(i = 0; i < root->sons_qty; i++)
		PrintTree(root->sons[i], level +1);
	return;
}

void
BuildNodes(struct nodeT * root, FILE * output)
{
	struct nodeT * aux = root;
	char nodeName[50] = {0};
	int i;

	if (root == NULL)
		return;

	sprintf(nodeName, "Node%d [label=\"%s\"];", aux->u_key, aux->key);
	fprintf(output, "%s\n", nodeName);

	for(i = 0; i < aux->sons_qty; i++){
		BuildNodes(aux->sons[i], output);
	}

	return ;
}

void
BuildArcs(struct nodeT * root, FILE * output)
{
	struct nodeT * aux = root;
	char nodeName[50] = {0};
	int i;

	if (root == NULL)
		return;



	for(i=0; i<aux->sons_qty; i++){
		if (aux->sons[i] != NULL)
		{
			sprintf(nodeName, "Node%d -> Node%d;", aux->u_key, aux->sons[i]->u_key);
			fprintf(output, "%s\n", nodeName);
			BuildArcs(aux->sons[i], output);
		}
	}
	return ;
}

void
BuildGraphViz(struct nodeT * root, char * file_output)
{
	FILE * output;

	output = fopen(file_output, "w");
	if(output == NULL){
		fprintf(stdout, "No se pudo crear el archivo %s\n", file_output);
	}

	fprintf(output, "digraph{\n//Creado por Simon, Nahuel y Juan\n//NODOS\n\n");

	BuildNodes(root, output);

	fprintf(output, "\n\n//EJES\n\n");

	BuildArcs(root, output);

	fprintf(output, "}\n");

	fclose(output);

	return;

}
